import static org.junit.Assert.*;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
 * 
 * @author kathryn.a.baldwin
 *
 */
public class VendingMachineTest {
        /**
         * Vending machines and vending machine items
         * for use in the functions
         */
        VendingMachine m;
        VendingMachineItem sprite, twix, snickers,cookies, gummies, pretzels,
        snowcaps,nerds;
        
        /**
         * A new vending machine is created for use in the 
         * functions
         */
        @Before
        public void setUp() throws Exception {
                m = new VendingMachine();
                
        }

        @After
        public void tearDown() throws Exception {
                
        }

        /**
         * Test to see that when a vending machine item is added to a 
         * vending machine in a particular slot, that it is correctly stored
         * in that slot (which is designated by its code).
         */
        @Test
        public void testAddItem() {
        
                
                sprite = new VendingMachineItem("Sprite",1.5);
                m.addItem(sprite, "A");
                assertTrue(m.getItem("A") == sprite);
                twix = new VendingMachineItem("Twix",.75);
                m.addItem(twix,m.B_CODE);
                assertTrue(m.getItem(m.B_CODE)== twix);
        }
        
        /**
         *testAddItems2
         *This test attempts to put two items in the same slot,
         *and should throw an error if working correctly. It 
         *should not allow two items to be put in the same slot. 
         */
        @Test
        public void testAddItem2()
        {
                
                snickers = new VendingMachineItem("snickers",.50);
                cookies = new VendingMachineItem("cookies",.80);
                m.addItem(cookies, "A");
                m.addItem(snickers,m.A_CODE);
                
                
        }
        
        /**
         * testRemoveItem
         * This test should show that an item 
         * can be removed from the vending machine,
         * thus causing the slot to become empty once
         * more
         */
        @Test
        public void testRemoveItem() {
                
                gummies = new VendingMachineItem("gummies",.50);
                //Boolean t = true;
                m.addItem(gummies,"B");
                
                System.out.println("Slot B contains:"+ m.getItem("B"));
                m.insertMoney(1);
                m.makePurchase("B");
                //m.removeItem("B");
                //assertEquals(("B".isEmpty()), true);
                //assertTrue(m.B_CODE.isEmpty());
                System.out.println("The B Slot is empty, yes?"+m.getItem("B"));
                m.addItem(gummies, "B");
                System.out.println("The B Slot is empty, yes?"+m.getItem("B"));
                m.makePurchase("B");
                System.out.println("The B Slot is empty, yes?"+m.getItem("B"));
        }
        
        /**
         * testRemoveItem2
         * Test that uses an invalid code when trying to remove 
         * an item from the vending machine. This should produce an 
         * error.
         */
        @Test
        public void testRemoveItem2()
        {
        
                gummies = new VendingMachineItem("gummies",2.0);
                m.addItem(gummies, "C");
        
                m.removeItem("H");
                
        }
        
        /**
         * testRemoveItem3
         * This test tries to remove an item from an empty slot
         * in the vending machine. This should throw an exception,
         * this should not be possible. 
         */
        @Test
        public void testRemoveItem3()
        {
                
                snickers = new VendingMachineItem("snickers",1.0);
                m.addItem(snickers, "A");
                
                m.removeItem("B");
                
                
        }
        
        /**
         * testInsertMoney
         * Test that checks to make sure money is inserted
         * into the vending machine correctly. 
         */
 
        @Test
        public void testInsertMoney() {
                double balance = 0;
                
                m.insertMoney(2.0);
                balance = balance + m.getBalance();
                assertEquals(2.0,balance,0);
                
        }
        
        /**
         * testInsertMoney2
         * This test tries to put in 0 money into
         * the vending machine and checks to see that 
         * it was inserted correctly. 
         */
        @Test
        public void testInsertMoney2()
        {
                double balance = 0;
        
                m.insertMoney(0);
                balance = balance + m.getBalance();
                assertEquals(0,balance,0);
                
        }
        
        /**
         * testInsertMoney3
         * This test checks to see if an exception is correctly
         * thrown when trying to input a negative amount into the 
         * vending machine. 
         */
        @Test
        public void testInsertMoney3()
        {
                double balance = 0;
                
                m.insertMoney(-2);
                balance = balance + m.getBalance();
                
                
        }
        
        /**
         * testInsertMoney4
         * This test adds money and then inputs a negative amount
         * greater than the money added. This should produce an 
         * error. 
         */
        @Test
        public void testInsertMoney4()
        {
                double balance = 0;
                m.insertMoney(3);
                m.insertMoney(-4);
                balance = balance + m.getBalance();
                
        }
        
        /**
         * testInsertMoney5
         * This test adds money and to the vending machine
         * and then tries to make a purchase for an item
         * of greater value than the money put in. This should
         * not be possible
         */
        @Test
        public void testInsertMoney5()
        {
                double balance = 0;
                
                cookies = new VendingMachineItem("cookies",5.0);
                m.insertMoney(3);
                m.addItem(cookies,"A");
                m.makePurchase("A");
                //balance = balance + m.getBalance();
                
                
        }
        @Test
        public void testInsertMoney6(){
        	double balance = 0;
        	cookies = new VendingMachineItem("cookies",6.00);
        	m.insertMoney(7);
        	m.addItem(cookies,"D");
        	m.makePurchase("D");
        }
        
        /**
         * testInsertMoney6
         * This test checks to see if you can insert money 
         * into the vending machine that would not be a real
         * currently value (1.2222). This should not be
         * possible. 
         */
        @Test
        public void testInsertMoney7()
        {
                
                m.insertMoney(10);
                m.insertMoney(1.2222);
                m.returnChange();
                
        }
        
        /**
         * testGetBalance
         * This test should check to see that the 
         * getBalance() function is working correctly.
         * After money is inserted, it should correctly 
         * return the amount of money currently in the 
         * vending machine. 
         */
        @Test
        public void testGetBalance() {
                
                m.insertMoney(5);
                assertEquals(5,m.getBalance(),0);
        }
        /**
         * testGetBalance2
         * This test checks to see that the starting
         * balance of the vending machine is 0
         */
        @Test
        public void testGetBalance2(){
                assertEquals(0,m.getBalance(),0);
        }
        /**
         * testGetBalance3
         * This test checks to see what getBalance()
         * returns if an attempt is made to purchase 
         * something worth more than the money in the 
         * vending machine, will it have a negative value?
         * It should instead not allow the purchase to be made.
         */
        @Test
        public void testGetBalance3(){
                m.insertMoney(4);
                snowcaps = new VendingMachineItem("snowcaps",6);
                m.addItem(snowcaps, "A");
                m.makePurchase("A");
                System.out.println("Balance: "+m.getBalance());
                
        }
        /**
         * testMakePurchase
         * This test checks to see that an item can be 
         * purchased that is in the vending machine 
         */
        @Test
        public void testMakePurchase() {
                pretzels = new VendingMachineItem("pretzels",2);
                m.addItem(pretzels, "A");
                m.makePurchase("A");
        }
        /**
         *testMakePurchase2
         *This test should attempt to make a purchase even
         *though no items have been placed in the vending 
         *machine. This should not be allowed.   
         */
        @Test
        public void testMakePurchase2(){
                pretzels = new VendingMachineItem("pretzels",2);
                m.makePurchase("A");
        }
        /**
         * testMakePurchase3
         * This test checks to see if a purchase can be made
         * for an empty slot. This should not be allowed according
         * to the comments for this makePurchase() function.
         */
        @Test
        public void testMakePurchase3(){
                pretzels = new VendingMachineItem("pretzels",2);
                m.addItem(pretzels,"A");
                System.out.println("Anything in slot B?"+m.getItem("B"));
                m.makePurchase("B");
        }
        /**
         * testReturnChange
         * This test has a user enter money, then make a purchase
         * for the item in slot A (which is less than the amount
         * of money they put in. 
         */
        @Test
        public void testReturnChange() {
                
        
                cookies = new VendingMachineItem("cookies",3.0);
                m.addItem(cookies,"A");
                m.insertMoney(6);
                System.out.println("Current balance:"+m.balance);
                m.makePurchase("A");
                
                m.returnChange();
                System.out.println("Balance after returning " +
                                "change"+m.balance);
                assertTrue(m.balance>= 0);
                m.insertMoney(12);
                System.out.println("Current balance:"+m.balance);
                m.makePurchase("A");
                m.returnChange();
                System.out.println("Current balance after returning" +
                                "change:"+m.balance);
                
        }
        /**
         * testReturnChange2
         * This test checks to see if change is returned when
         * the exact amount of money is in the vending machine
         * for the item selected for purchase. 
         */
        @Test
        public void testReturnChange2(){
                nerds = new VendingMachineItem("nerds",1);
                m.addItem(nerds, "A");
                m.insertMoney(1);
                System.out.println("Current balance:"+m.balance);
                m.makePurchase("A");
                m.returnChange();
                System.out.println("Current balance:"+m.balance);
        }
        
        /**
         * testReturnChange3
         * This test tries to begin with a negative balance, 
         * then adds money to give it a positive balance.
         * Then tries to return the change. It should not be
         * able to start with a negative balance, according
         * to the comments for returnChange()
         */
        @Test
        public void testReturnChange3(){
                m.balance = -2;
                m.insertMoney(4);
                System.out.println("Current balance:"+m.balance);
                m.returnChange();
                System.out.println("Current balance after returning change:"+m.balance);
        }

}

